
/***************************** 68000 SIMULATOR ****************************

File Name: CODE5.C
Version: 1.0

The instructions implemented in this file are the binary coded decimal
   operations:

		ABCD, SBCD, NBCD

   Modified: Chuck Kelly
             Monroe County Community College
             http://www.monroeccc.edu/ckelly

***************************************************************************/


#include <stdio.h>
#include "extern.h"         /* contains global "extern" declarations */



//-------------------------------------------------------
// perform the ABCD operation
int	ABCD()
{
  int	Rx, Ry, carry, temp_result;

  Rx = (inst >> 9) & 0x0007;
  Ry = inst & 0x0007;

  if (inst & 0x0008) // Rx & Ry are address registers used in predecrement mode
  {
    Rx = a_reg(Rx);
    Ry = a_reg(Ry);
    A[Rx]--;
    A[Ry]--;

    //source = memory[A[Ry]];     //ck 4-2006 replace with below
    mem_req ((int)A[Ry], BYTE_MASK, &source); // cause bus error on bad access
    //dest = memory[A[Rx]];      //ck 4-2006 replace with below
    mem_req ((int)A[Rx], BYTE_MASK, &dest);

  }
  else		// Rx & Ry are data registers
  {
    source = D[Ry] & BYTE_MASK;
    dest = D[Rx] & BYTE_MASK;
  }

  // perform the ABCD operation
  result = ((SR & xbit) >> 4) + (source & 0xf) + (dest & 0xf);
  if (result > 9)
  {
    result = result - 10;
    carry = 1;
  }
  else
    carry = 0;
  temp_result = ((source >> 4) & 0xf) + ((dest >> 4) & 0xf) + carry;
  if (temp_result > 9)
  {
    temp_result = temp_result - 10;
    carry = 1;
  }
  else
    carry = 0;

  result = result + (temp_result << 4);

  if (inst & 0x0008)
    put ((long *)&memory[A[Rx]], result, (long) BYTE_MASK);
  else
    put (&D[Rx], result, (long) BYTE_MASK);
  if (carry)
    SR = SR | cbit;
  else
    SR = SR & ~cbit;

  cc_update (GEN, UND, CASE_1, UND, N_A, source, dest, result, (long) BYTE_MASK, 0);

  inc_cyc ( (inst & 0x0008) ? 18 : 6);

  return SUCCESS;
}



//-------------------------------------------------------
// perform the SUB operation
int	SBCD()
{
  int	Rx, Ry, borrow, temp_result;

  Rx = (inst >> 9) & 0x0007;
  Ry = inst & 0x0007;

  if (inst & 0x0008) //Rx & Ry are address registers used in predecrement mode
  {
    Rx = a_reg(Rx);
    Ry = a_reg(Ry);
    A[Rx]--;
    A[Ry]--;

    //source = memory[A[Ry]];     //ck 4-2006 replace with below
    mem_req ((int)A[Ry], BYTE_MASK, &source); // cause bus error on bad access
    //dest = memory[A[Rx]];      //ck 4-2006 replace with below
    mem_req ((int)A[Rx], BYTE_MASK, &dest);

  }
  else
  {		        // Rx & Ry are data registers
    source = D[Ry];
    dest = D[Rx];
  }

  // perform the SBCD operation
  result = (dest & 0xf) - (source & 0xf) - ((SR & xbit) >> 4);
  if (result < 0)
  {
    result = result + 10;
    borrow = 1;
  }
  else
    borrow = 0;
  temp_result = ((dest >> 4) & 0xf) - ((source >> 4) & 0xf) - borrow;
  if (temp_result < 0)
  {
    temp_result = temp_result + 10;
    borrow = 1;
  }
  else
    borrow = 0;
  result = result + (temp_result << 4);

  if (inst & 0x0008)
    put ((long *)&memory[A[Rx]], result, (long) BYTE_MASK);
  else
    put (&D[Rx], result, (long) BYTE_MASK);

  if (borrow)
    SR = SR | cbit;
  else
    SR = SR & ~cbit;

  cc_update (GEN, UND, CASE_1, UND, N_A, source, dest, result, (long) BYTE_MASK, 0);

  inc_cyc ( (inst & 0x0008) ? 18 : 6);

  return SUCCESS;
}



//-------------------------------------------------------
// perform the NBCD operation
int	NBCD()
{
  int	borrow, temp_result;

  int error = eff_addr((long)BYTE_MASK, DATA_ALT_ADDR, true);
  if (error)              // if address error
    return error;         // return error code

  dest = EV1 & BYTE_MASK;

  result = 10 - (dest & 0xf) - ((SR & xbit) >> 4);
  if (result < 10)
    borrow = 1;
  else {        // dest was 0 so 0-0 result should be 0 ck 8-10-2005
    borrow = 0;
    result = 0;
  }

  temp_result = 10 - ((dest >> 4) & 0xf) - borrow;
  if (temp_result < 10)
    borrow = 1;
  else {        // dest was 0 so 0-0 result should be 0 ck 8-10-2005
    borrow = 0;
    temp_result = 0;
  }

  result = result + (temp_result << 4);

  if (borrow)
    SR = SR | cbit;
  else
    SR = SR & ~cbit;

  put (EA1, result, (long) BYTE_MASK);
  cc_update (GEN, UND, CASE_1, UND, N_A, source, dest, result, (long) BYTE_MASK, 0);
  inc_cyc ( (inst & 0x0030) ? 8 : 6);
  return SUCCESS;
}

